package com.xzakota.minesweeper.ui.dialog;

import com.xzakota.minesweeper.Client;
import com.xzakota.minesweeper.model.entity.RoomBean;
import com.xzakota.minesweeper.model.entity.UserBean;
import com.xzakota.minesweeper.msg.*;
import com.xzakota.minesweeper.ui.IWindow;
import com.xzakota.minesweeper.ui.dialog.templae.AbstractBaseDialog;
import com.xzakota.minesweeper.ui.dialog.templae.MessageDialog;
import com.xzakota.minesweeper.ui.dialog.templae.SwingWorkerWaitDialog;
import com.xzakota.minesweeper.ui.frame.MultiPlayerGameFrame;
import com.xzakota.minesweeper.widget.RoomInfoPanel;
import com.xzakota.minesweeper.widget.UserInfoPanel;

import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;

/**
 * 房间预览对话框
 *
 * @author Xzakota
 */
public class RoomDialog extends AbstractBaseDialog {
    private static final Map<Integer, RoomInfoPanel> roomPanelMap = new HashMap<>();
    private final IWindow parent;
    private final List<UserBean> list = new ArrayList<>();
    private UserBean currentUser;

    public RoomDialog(IWindow parent) {
        super(null);
        this.parent = parent;

        setTitle("房间预览");

        currentUser = Client.getClient().currentUser;
        if (currentUser == null) {
            currentUser = new UserBean("XXX", "", "");
        }

        PropertyChangeListener listener = evt -> {
            if ("ROOM".equals(evt.getPropertyName())) {
                Client.ROOM.forEach((k, v) -> {
                    Map<?, ?> newValue = (Map<?, ?>) evt.getNewValue();
                    RoomBean room = (RoomBean) newValue.get(k);
                    roomPanelMap.get(k).setOnlineUsers(room.roomCurrentOnline);
                });
            }
        };

        Client.getClient().addPropertyChangeListener(listener);

        addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                super.windowClosing(e);

                closeWindow();
            }

            @Override
            public void windowClosed(WindowEvent e) {
                super.windowClosed(e);

                Client.getClient().removePropertyChangeListener(listener);
            }
        });

        initLayout();
        updateUI();
    }

    public void initLayout() {
        JPanel rootPanel = new JPanel(new BorderLayout());

        // =================== 用户面板 ===================
        UserInfoPanel topPanel = new UserInfoPanel(currentUser);
        topPanel.setAccentColor(true);

        rootPanel.add(topPanel, BorderLayout.NORTH);
        // ===============================================

        // =================== 操作面板 ===================
        JPanel mainPanel = new JPanel();
        mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
        mainPanel.setBorder(BorderFactory.createCompoundBorder(
                BorderFactory.createEmptyBorder(10, 10, 10, 10),
                BorderFactory.createLoweredSoftBevelBorder())
        );

        JLabel welcomeLabel = new JLabel("欢迎来到扫雷！");
        welcomeLabel.setFont(new Font("黑体", Font.BOLD, 20));
        mainPanel.add(welcomeLabel);
        mainPanel.add(Box.createVerticalStrut(12));

        Client.ROOM.forEach((k, v) -> {
            RoomInfoPanel roomInfoPanel = new RoomInfoPanel();
            roomInfoPanel.setRoomLabel("房间" + k + ": ");
            roomInfoPanel.setRoomButtonActionListener(e -> {
                enterRoom(k);
            });
            roomInfoPanel.setOnlineUsers(v.roomCurrentOnline);
            roomInfoPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
            roomPanelMap.put(k, roomInfoPanel);
            mainPanel.add(roomInfoPanel);
            mainPanel.add(Box.createVerticalStrut(8));
        });

        rootPanel.add(mainPanel, BorderLayout.CENTER);
        // ===============================================

        setContentPane(rootPanel);
    }

    @Override
    public void showWindow() {
        super.showWindow();
    }

    private void enterRoom(int roomNum) {
        SwingWorkerWaitDialog waitDialog = new SwingWorkerWaitDialog();
        waitDialog.setTipText("正在进入房间中...");
        waitDialog.worker = new SwingWorkerWaitDialog.Worker() {
            @Override
            public Boolean doInBackground() {
                Object[] msg = {currentUser, roomNum};

                UserEnterRoomMsg sendMsg2 = new UserEnterRoomMsg();
                sendMsg2.data = msg;

                RoomRankMsg sendMsg3 = new RoomRankMsg();
                sendMsg3.data = msg;

                final boolean[] result = {false, false};

                CountDownLatch latch = new CountDownLatch(2);
                waitDialog.doReleaseEvent();
                waitDialog.tempThread = new Thread(() -> {
                    Client client = Client.getClient();
                    while (client.socketState != 1 && !Thread.currentThread().isInterrupted()) {
                    }
                    MsgHandler handler2 = new MsgHandler() {
                        @Override
                        public void handle(BaseMsg msg) {
                            if (msg.code == MsgCode.BASE_SUCCESS) {
                                result[0] = true;
                            }
                            new MessageDialog(SignInMsgDefaultHandler.resultMsgText).showWindow();
                            MsgHandlerFactory.removeMsgHandler(MsgHandlerFactory.MSG_TYPE_ENTER_ROOM, this);
                            latch.countDown();
                        }
                    };
                    MsgHandler handler3 = new MsgHandler() {
                        @Override
                        public void handle(BaseMsg msg) {
                            if (msg.code == MsgCode.BASE_SUCCESS) {
                                result[1] = true;
                                list.addAll(((RoomRankMsg) msg).getRank());
                            }
                            MsgHandlerFactory.removeMsgHandler(MsgHandlerFactory.MSG_TYPE_ROOM_RANK, this);
                            latch.countDown();
                        }
                    };
                    MsgHandlerFactory.addMsgHandler(MsgHandlerFactory.MSG_TYPE_ENTER_ROOM, handler2);
                    Client.getClient().sendMsg(sendMsg2);
                    MsgHandlerFactory.addMsgHandler(MsgHandlerFactory.MSG_TYPE_ROOM_RANK, handler3);
                    Client.getClient().sendMsg(sendMsg3);
                });
                waitDialog.tempThread.start();

                try {
                    latch.await();
                } catch (InterruptedException ex) {
                    throw new RuntimeException(ex);
                }

                return result[0] && result[1];
            }

            @Override
            public void doneSuccess() {
                dialogResult = true;
                Client.getClient().enterRoomNum = roomNum;
                MultiPlayerGameFrame gameFrame = new MultiPlayerGameFrame(parent, roomNum, list);
                closeWindow();
                gameFrame.showWindow();
            }

            @Override
            public void doneFail() {
                dialogResult = false;
            }
        };
        waitDialog.showWindow();
    }
}
